#include <stdio.h>
#include <stdlib.h>
#include "Operation.h"

#include <math.h>
#include <SDL/SDL.h>
#if (defined(__APPLE__))
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#include "repere.h"
#include "Camera.h"
#ifndef M_PI
#define M_PI       3.14159265358979323846
#endif
extern int readFile();
extern FILE* yyin;
/*extern double result[];*/

/*coordonnee polaire*/
double val_rayon[2080];
double tab_phi[2080];
double tab_theta[2080];

/*coordonnee cartesienne*/
double coorX[2080];
double coorY[2080];
double coorZ[2080];

/*pour la camera*/
float posCamera[] = {3, 0, 3};
float lookAtCamera[] = {0, 0, 0};

void DrawObject();
void LaunchApp(int argc, char * argv[]);
void DrawSphere();

int main(int argc, char * argv[]) {
    int i;
    double c_phi, c_theta;
    double step_phi = M_PI / 32, step_theta = M_PI / 32;
    double retour[1];
    double paramPhi[1];
    double paramTheta[1];

    int compteur = 0;

    for (i = 0; i < 2080; i++) {
        val_rayon[i] = 0;
        tab_phi[i] = 0;
        tab_theta[i] = 0;
    }

    if (argc < 2)
        return;
    /*calcul pour tout les phi et pour tout les theta la valeur du rayon donnee par l'equation*/
    /*on a nos tableaux de points phi, theta, r*/
    for (c_theta = -(M_PI / 2); c_theta < M_PI / 2; c_theta += step_theta) {
        for (c_phi = 0; c_phi < 2 * M_PI; c_phi += step_phi) {
            /* pour obliger yyparse a retraiter le fichier, on le reouvre :/ */
            yyin = fopen(argv[1], "r");
            if (yyin == NULL) {
                return;
            } else {
                /*appel a yyparse*/
                paramPhi[0] = c_phi;
                paramTheta[0] = c_theta;
                readFile(retour, paramPhi, paramTheta);
                val_rayon[compteur] = retour[0];
                tab_phi[compteur] = c_phi;
                tab_theta[compteur] = c_theta;
                fclose(yyin);
                compteur++;
            }

        }
    }

    /*On convertit en valeur cartesienne*/

    for (i = 0; i < 2080; i++) {
        coorX[i] = val_rayon[i] * cos(tab_phi[i]) * cos(tab_theta[i]);
        coorY[i] = val_rayon[i] * cos(tab_phi[i]) * sin(tab_theta[i]);
        coorZ[i] = val_rayon[i] * sin(tab_phi[i]);
    }
    /* on lance le rendu*/
    LaunchApp(argc, argv);

    return 0;
}

/* pour les tests openGL*/
void DrawSphere() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3ub(80, 80, 200);
    GLUquadric* params = gluNewQuadric();
    gluQuadricDrawStyle(params, GLU_LINE);
    gluSphere(params, 1, 30, 25);
    glFlush();
}

/* fonction qui creer des glvertex en fonction des tableau qu'on lui donne*/
void DrawObject() {
    int j = 0;
    glBegin(GL_LINES);

    for (j = 0; j < 2080 - 1; j++) {
        glColor3ub(100, 100, 255);
        glVertex3f(coorX[j], coorY[j], coorZ[j]); /* origin of the line*/
        glVertex3f(coorX[j + 1], coorY[j + 1], coorZ[j + 1]); /* end of the line*/

    }

    glEnd();
}

void LaunchApp(int argc, char * argv[]) {
    printf("\n\n\n\n\n\n\n\n\n\n");
    printf("=================================================\n");
    printf("=============Gestion de la camera =======================\n");
    printf("=================================================\n");
    printf("c'est le world qui bouge et non la camera...  glulookat a debuger...\n");
    printf(" z -> avance sur x\n");
    printf(" s -> recule sur x\n");
    printf(" q -> avance sur y\n");
    printf(" d -> recule sur y\n");
    printf(" a -> avance sur Z\n");
    printf(" e -> recule sur Z\n");
    printf("=================================================\n");
    printf(" fleche up -> rotation axe Z\n");
    printf(" fleche down -> rotation axe Z\n");
    printf(" fleche left -> rotation axe x\n");
    printf(" fleche right -> rotation axe x\n");
    printf("TODO rotation axe Y\n");
    printf("=================================================\n");
    printf(" page+  -> zoom+\n");
    printf(" page-  -> zoom-\n");
    printf("=================================================\n");
    printf("retour -> centre la vue comme au debut du lancement de l'appli\n");
    printf("echap -> exit\n");
    printf("===============   ENJOY     ===========================\n");
    SDL_Event event;
    SDL_Init(SDL_INIT_VIDEO);
    atexit(SDL_Quit);

    SDL_WM_SetCaption("SDL GL Application", NULL);
    SDL_SetVideoMode(1000, 600, 32, SDL_OPENGL); /*| SDL_FULLSCREEN);*/

    Uint32 last_time = SDL_GetTicks();
    Uint32 current_time, ellapsed_time;
    Uint32 start_time;

    SDL_EnableKeyRepeat(100, 100);

    glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(70, (double) 640 / 480, 1, 1000);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(posCamera[0], posCamera[1], posCamera[2],
            lookAtCamera[0], lookAtCamera[1], lookAtCamera[2],
            0, 0, 1);

    glEnable(GL_DEPTH_TEST);

    for (;;) {
        start_time = SDL_GetTicks();
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    exit(0);
                    break;
                case SDL_KEYDOWN:
                    switch (event.key.keysym.sym) {
                        case SDLK_ESCAPE:
                            exit(0);
                            break;

                        case SDLK_BACKSPACE:
                            /*reinitialisation de la scene*/
                            Camera_BACKSPACE();
                            break;
                            /*==================*/
                            /*====== ZOOM =======*/
                            /*==================*/
                        case SDLK_PAGEUP:
                            Camera_PAGEUP();
                            break;
                        case SDLK_PAGEDOWN:
                            Camera_PAGEDOWN();
                            break;
                            /*=========================*/
                            /*====== Orientation cam =======*/
                            /*========================*/
                        case SDLK_UP:
                            Camera_UP();
                            break;
                        case SDLK_DOWN:
                            Camera_DOWN();
                            break;
                        case SDLK_LEFT:
                            Camera_LEFT();
                            break;
                        case SDLK_RIGHT:
                            Camera_RIGHT();
                            break;
                            /*=========================*/
                            /*====== déplacement cam =======*/
                            /*========================*/
                        case SDLK_z:
                            Camera_z();
                            break;
                        case SDLK_s:
                            Camera_s();
                            break;
                        case SDLK_q:
                            Camera_q();
                            break;
                        case SDLK_d:
                            Camera_d();
                            break;
                        case SDLK_a:
                            Camera_a();
                            break;
                        case SDLK_e:
                            Camera_e();
                            break;
                        default:
                            break;
                    }
                    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            }
        }
        current_time = SDL_GetTicks();
        ellapsed_time = current_time - last_time;
        last_time = current_time;
        /*Pour eviter de tuer le CPU*/
        ellapsed_time = SDL_GetTicks() - start_time;
        if (ellapsed_time < 10) {
            SDL_Delay(10 - ellapsed_time);
        }

        DrawObject();
        DrawRepere();


        glFlush();
        SDL_GL_SwapBuffers();
    }
}
